For any suggestions or feedback regarding these notes,
please contact Pragy Agarwal
(20-25 mins)
(25-20 mins)
Find existing companies / systems that offer a similar product / feature.
Gives you an overview of the umbrella of different scopes that you can consider.
Typeahead is a specific form of autocomplete.
Try to type-ahead of the user
but typeahead is always followed by with some form of search.
Autocomplete is available in many different settings
Autocomplete is typically local to your machine. Any suggestions are specific to you. Autocomplete is standalone.
Typeahead is always associated with search.
The list of suggestions in typeahead are the most popular queries searched globally in the past, that match the given prefix.
Always keep the "minimal" in your mind. MVP features is not a feature suggestion competition.
MVP features perfect for discussion | Future Scope | Bad |
As the user is typing in the search-box, we should auto-complete their search query. typeahead(partial_query) => suggestions_list user-facing | Typeahead results should be personalized
| Display a textbox in which the user can type something (frontend) |
The suggestions shown in typeahead are popular searches that other people have made in the past log_search(search_query) => void internal | Results should take recency/news factor into consideration | Clicking a typeahead suggestion should lead to a search (frontend) |
We will limit to showing only top 5, relevant suggestions.
| Fix typos/Spell-correct the user's partialQuery before showing the typeahead results | While showing the suggestions, the part that has already been typed should be highlighted (frontend) |
With every letter that the user types, the typeahead suggestions should change | Even when the user has typed < 3 characters, we should suggest the "trending" global searches / previous recent searches by the user | after giving suggestions, if user press tab button, it should write copy the query in the text box (frontend) |
We will start showing typeahead suggestions only
| user age based personalization | |
Grammar-correct the user's partialQuery before showing the typeahead results | ||
provide suggestions as per the law of the land |
For every feature that you discuss, think of the following
typeahead(partial_query) => suggestions_list
user-facing
log_search(search_query) => void
internal
GET /typeahead?partialQuery={}
API: input & output (interface)
Protocol: how the communication happens (REST / ...)
Where does the list of suggestions come from?
Users are constantly searching on Google.
Every time a user makes a search (search_query)
(design goals)
Do NOT jump to an answer
Past search queries and their corresponding counts.
Search Query | Count |
why is the sky blue? | 49,999 |
why is water wet? | 50,000 |
what is the color of the ocean | 5,000 |
When is the data changing?
Everytime someone makes a search, the count of some entry changes.
Everytime someone makes a search, the top-5 relevant results for some typeahead partial_query changes.
It is possible for the search-count to reflect in a delayed manner in the top-5 results.
For some time, it is possible that the true count of Query1 > Query2, but we still show Query2 before Query1 in the typeahead suggestions.
Yes, that's okay
Data loss would happen if someone has searched for a query, but for whatever reason, we were not able to increment the count for that query (query didn't get logged).
The counts will be off by a small amount.
Search Query | True Count |
why is suryakumar dropped? | 49,999 |
why is water wet? | 50,000 |
what is the color of the ocean | 5,000 |
Search Query | DB Count |
why is suryakumar dropped? | 49,999 |
why is water wet? | 49,998 |
what is the color of the ocean | 5,000 |
Yes, that's okay.
(same reasons as above)
What are our latency requirements?
Ultra-low latency - literally competing with the user's typing speed!
each typeahead query to take < 10ms
(this doesn't include the round trip - that depends on the user's distance from the servers - don't have much control over that - only solution for that is to have geolocated servers)
The scale will dictate our design choices
All these things will help us guide our choice of database, cache, & sharding
No. Back-of-the-envelope estimates.
being off by a factor of 2 or 3 is okay.
Actual value: 100
You suggest: 50 okay
You suggest: 200 okay
You suggest: 10 not okay (off by a factor of 10)
However, any estimates that you make should be justified. Don't pull out numbers from thin air. You will have to make some assumptions - each assumption should be clearly stated as such.
Start by estimating the number of daily active users.
World Population: ~8 billion
Number of Internet Users: ~5 billion
India's Population: ~1.4 billion
USA's Population: ~350 million
Only 20% of your users will be active.
Can be extended to the 80-20-1 principle for social media
assumption: Google has 5 billion users.
Daily Active Users (DAU): 20%
= 20% of 5 billion users
= 1 billion users
assumption: Number of searches per active-user per day: 20
Total number of searches / day
= (20 searches / user / day) * (1 billion users)
= 20 searches / day * 1 billion
= 20 billion searches / day
Avg. searches / second
= 20 billion searches / day
= 20 * 10^9 searches / (10^5 seconds) (1 day = 86400 seconds ~ 10^5 seconds)
= 200,000 searches / second
Note: searches are going to search API, not the typeahead API
assumption: Number of typeahead queries per search query: 10
avg size of a search query is 10 letters
we will start showing suggestions after the first 3 letters
number of typeaheads per search would be (10 - 3) = 7 ~ 10
Everytime a user is searching for something, they will first type the query, and then they will search.
search_query: "why is the sky blue"
= (200,000 searches / second) * (10 typeaheads / search)
= 2 million typeaheads / second
Every time a search is made, the /search microservice pings the /typeahead microservice
= 200,000 requests / second
= 5x the average load
= 5 * (2 million typeaheads / second)
= 10 million typeaheads / second
What's the data?
Past search queries & their counts
Search Query | True Count |
why is suryakumar dropped? | 49,999 |
why is water wet? | 50,000 |
what is the color of the ocean | 5,000 |
Avg. size of search query: 10 letters (made this assumption earlier)
How many entries in this table?
No. Because for new searches, we're adding entries
But for queries that have already been searched earlier, we're just updating the counts
The number of entries in the table will depend on the number of "unique" (never seen before in the history of Google) search queries that happen
assumption: % of search queries are new (never seen before) = 0.1%
assumption: % of search queries are new (never seen before) = 10%
number of new entries / day
= 10 % of (20 billion searches / day)
= 2 billion entries per day
amount of data / day
= (10 bytes / entry) * (2 billion entries / day)
= 20 GB / day
total amount of data (over 20 years)
= (20 GB / day) * (20 years)
= (20 GB / day) * (20 * 400 days) (365 ~= 400)
= 16 * 10^4 GB
= 160 TB
Probably yes, with modern storage.
But, will a single server be able to handle 10 million requests / second?
Absolutely no!
We need sharding!
typeahead => read query => 2 million requests / second
log_search => write query => 200,000 requests / second
reads are 10x more than writes
We will call this read heavy, because even though the system has to handle lots of writes too, it is dominated by reads.
Whenever you've read heavy systems & the writes are also significant
No database system is optimized for both reads & writes (that's impossible)